//Version 15 - Parte A y B:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

int parsing(char line[], char* args[], char type1[], char type2[]);
void command(char* args[], char* path);
void seek(char *arreglo[]);
void changeDir(char* args[], char* path);
void showPrompt();

char* directories[100];
char* PATH;
int banderamp;

int main(int argc, char *argv[]){
	printf("--------------------------BAASH--------------------------\n");
    char* args[100];   
	char line[1024];
    PATH = getenv("PATH");
    int cantarg;
    parsing(PATH, directories, ":",":");
        
    while(1){  
		banderamp=0;
        showPrompt();                            //Muestra el prompt
        if (fgets(line, 1024, stdin) == NULL) return 0;
        else{
			cantarg=parsing(line, args, " ", " \n");    //Parsea la linea de entrada.
			if(strcmp(args[cantarg-1],"&")==0){
				//printf("encontre &\n");
				args[cantarg-1] = NULL;
				cantarg--;
				banderamp=1;
			}
            command(args, getcwd(NULL, 0));     //interpreta el comando (agrs[0])
        }
    }
       
    return 0;
}

//Muestra el prompt
void showPrompt(){
    printf("%s # %s > ", getenv("LOGNAME"),(char*) getcwd(NULL, 0));           	
}

//Parsea una linea
int parsing(char line[], char* args[], char type1[], char type2[]){ 
	int i = 0;
    args[i] = strtok(line, type1);    
    while((args [i]) != NULL) {
		i++;
        args[i] = strtok (NULL, type2);
    }
    return i;
}

//Interpreta el argumento: si es cd llama a changedir(), si no es cd llama a seek().
void command(char* args[], char* path){
	if(strcmp(args[0], "exit\n") == 0) exit(1);
	if(strcmp(args[0], "\n") == 0) return;
    if(strcmp(args[0], "cd") == 0) changeDir(args, path);
    else seek(args);
}

//Cambia el directorio, sea relativo o absoluto
void changeDir(char* args[], char* path){
	if( chdir(args[1]) != 0 ) printf("Command not found\n");
		else path = (char*) getcwd(NULL, 0);
}

//Buscaqueda en secuencia PATH,  
void seek(char *args[]){
    char str[200];
    int flag = 0;
    int num = 0;
    pid_t pid;

    //En cada uno de los caminos debo probar si esta el comando 
    if ( (pid = fork()) == 0){
// HIJO ---------------------------------------------------------------------------------------
//Si comienza con un ./ o   ../------------------------------------------
       //printf("Estoy en hijo\n");
       if(args[0][0]=='.'){
			char * aux1;
			char * aux2;
			int status = 0;
			aux1 = strtok(args[0],"/");	
			aux2 = aux1;
			while((status == 0)&&((aux1 = strtok(NULL,"/"))!= NULL)){
				status = chdir(aux2);
				aux2 = aux1;		
			}					
			char* path = (char*) getcwd(NULL, 0);   //Encuentra el pwd.
			strcat (path,"/");
			strcat (path,aux2);	
			strncpy(str,path,sizeof(str));
			//Quita el final de linea, solo si no habia & (ya que si habia, fue quitado):
			if (banderamp==0){		
				int j=0;
				while(str[j]!='\0')j++;                
					int n=0;
					for(n=0;n<j;n++){
					if((str[n]=='\n')||(str[n]=='\0'))str[n]='\0';
				}
			}  
			
			if((access(str,F_OK))==0){
				execv(str, args);
				printf("Termino hijo\n");
				exit(1);
			}
			else{
				printf("\nERROR, EL ARCHIVO NO HA SIDO ENCONTRADO \n");
				exit(1);
				}
			}
//Si no comienza con un ./ o / -------------------------------------------
			else{
				int i = 0;        
                char* dir[100];
                
                while( directories[i] != NULL ){
					
					//Busca en PATH el comando especificado:    
					//Arma el string = path + / + comando:    
                    dir[i] = directories[i];
                    strcpy (str, dir[i]);                            
                    strcat (str, "/");
                    strcat(str, args[0]);
					//Quita el final de linea, solo si no habia & (ya que si habia, fue quitado):
                    if (banderamp==0){
						int j = 0;
						while(str[j]!='\0')j++;                
                                
						if ( args[1] != NULL ) str[j] = '\0';
						else str[j-1] = '\0';
                    }
                    //Si lo encuentra lo ejecuta:
                    if( (access(str,F_OK)) == 0 ){
                        execv(str, args);
                        printf("Termino hijo\n");
                        num = 1;
                    }
						else i++;//Si no lo encientra incrementa i, para buscar en otro directorio.
				}//Fin del ciclo whle.
                
                //Si no encontro el comando en todo PATH muestra un mensaje de error:
                if( num == 0 ){
					printf("\nEl archivo no ha sido encontrado\n");
                    exit(1);
                }
			}
                
	}
// PADRE ---------------------------------------------------------------------------------------
		else if ( pid>0 ){
			//printf("Estoy en padre \n");
            flag =-1;
        }
		
		//Si no habia &, espera al hijo
		if(banderamp!=1){
			waitpid(pid, &flag, 0);
			args=NULL;			
		}
		//Si habia &, no lo espera
		else {
			args = NULL;
			waitpid(pid, &flag, WNOHANG);
		}
	
}
